<template>
  <div class="yu-input">
    <div class="left-input">
      <input :type="inputType" :value="value" :maxlength="maxlength" required @input="change"  @blur="blur"/>
      <span>{{ title }}</span>
      <transition enter-active-class="animate__animated animate__zoomIn">
        <b v-if="isMessage">{{ rules[messageIndex].message }}</b>
      </transition>
      <i></i>
    </div>
    <span style="margin-left: 2px;">
      <slot name="yuSlot"></slot>
    </span>
  </div>
</template>

<script setup>
import {reactive, toRefs} from "vue";
import {useStore} from "@/store/index";

const store = useStore()
const props = defineProps({
  title: String, // 标题
  inputType: { // input类型
    type: String,
    default: 'text'
  },
  width: { // 整个组件宽度
    type: String,
    default: '200px'
  },
  value: { // 父组件传递的值
    type: String
  },
  rules: { // 正则校验
    type: Array,
    default: []
  },
  maxlength: Number, // 最大长度
  lineColor: { // 底部渐变色
    type: String,
    default: 'linear-gradient(90deg, #ff1b69, #ff0, #2196f3, #9c27b0, #ff1b69)'
  }
})

const data = reactive({
  isMessage: false, // 是否显示报错信息
  messageIndex: 0 // 报错信息下标
})

const { isMessage, messageIndex } = toRefs(data)

const $emit = defineEmits(['update:value'])

// 校验是否符合
const rulesFn = (value) => {
  props.rules.forEach((item, index) => {
    // 通过正则校验，就不展示报错信息
    if (item.pattern.test(value || props.value)) {
      data.isMessage = false
    } else {
      data.isMessage = true
      data.messageIndex = index
    }
  })
  return data.isMessage
}
// 值改变时触发
const change = (e) => {
  rulesFn(e.target.value)
  // 不需要父组件操作可以改变父组件值
  $emit('update:value', e.target.value)
}

// 失去焦点的时候触发
const blur = (e) => {
  rulesFn(e.target.value)
  // 不需要父组件操作可以改变父组件值
  $emit('update:value', e.target.value)
}

// 抛出事件给外部调用
defineExpose({
  rulesFn
})
</script>

<style scoped lang="scss">
$inputWidth: v-bind(width);
.yu-input {
  position: relative;
  display: flex;
  align-items: center;
  width: $inputWidth;
  margin-bottom: 40px;
  .left-input {
    flex: 1;
    span {
      position: absolute;
      top: 0;
      padding: 10px 0 5px;
      font-size: 20px;
      display: flex;
      color: v-bind('store.theme.titleTextColor');
      transition: 0.5s linear;
    }

    input {
      width: 100%;
      outline: none;
      border: 0;
      background-color: transparent;
      height: 2rem;
      color: v-bind('store.theme.titleTextColor');
      padding: 4px;
      letter-spacing: 0.1em;
      &:valid, &:focus {
        ~ span {
          color: v-bind('store.theme.hoverTextColor');
          transform: translateY(-20px);
          font-size: 14px;
        }
        ~ i {
          &::before {
            left: 0;
          }
        }
      }
    }

    i {
      position: absolute;
      bottom: -20px;
      left: 0;
      width: 100%;
      height: 2px;
      display: inline-block;
      background-color: white;
      overflow: hidden;
      &::before {
        content: '';
        position: absolute;
        display: inline-block;
        width: 100%;
        height: 100%;
        left: -100%;
        background: v-bind(lineColor);
        animation: keyI 2s linear infinite;
      }
    }
    @keyframes keyI {
      0% {
        background-position-x: 0;
      }
      100% {
        background-position-x: $inputWidth;
      }
    }
    b {
      font-weight: normal;
      color: v-bind('store.theme.hoverTextColor');
      font-size: 12px;
    }
  }
  .right-slot {

  }
}

</style>
